package air_traffic_control;

import java.util.HashMap;
import java.util.Map;
import air_traffic_control.Plane;
import air_traffic_control.TimerTickListener;

public class Airport implements TimerTickListener {
	public static final int NO_AVAILABLE_TRACK = -1;

	private final int NUMBER_OF_TRACKS;
	private final int CAPACITY;
	private final int TIME_TO_LAND_OR_TAKE_OF;

	// tracks[i] will show for how much time the i-th track will be busy
	private int[] tracks;
	private Map<String, Integer> planesToTracks = new HashMap<String, Integer>();

	public Airport(int numberOfTracks, int capacity, int time) {
		NUMBER_OF_TRACKS = numberOfTracks;
		CAPACITY = capacity;
		TIME_TO_LAND_OR_TAKE_OF = time;

		tracks = new int[NUMBER_OF_TRACKS];
	}

	// This method show whether the plane can land to the airport.
	// The returned value is the index of the track that the plane can land
	// If there is no free track NO_AVAILABLE_TRACK constant is returned
	public int requestToLand(Plane plane) {

		if (planesToTracks.size() >= CAPACITY)
			return NO_AVAILABLE_TRACK;

		int trackNumber = NO_AVAILABLE_TRACK;

		int indexOfLeastOccupied = 0;

		for (int i = 1; i < tracks.length; ++i) {
			// check for tracks[i] >= 0, because if tracks[i] < 0 the track is
			// closed
			if (tracks[i] < tracks[indexOfLeastOccupied]) {
				indexOfLeastOccupied = i;
			}
		}

		if (tracks[indexOfLeastOccupied] + TIME_TO_LAND_OR_TAKE_OF <= plane
				.getFuel()) {
			trackNumber = indexOfLeastOccupied;
			planesToTracks.put(plane.getName(), indexOfLeastOccupied);

			tracks[indexOfLeastOccupied] += TIME_TO_LAND_OR_TAKE_OF;

		}

		return trackNumber;
	}

	// This will return the number of track
	public int requestToTakeOff(String planeName)
			throws UnregisteredPlaneException {
		validatePlaneName(planeName);

		// we already know from where the plane will take off

		int trackNumber = planesToTracks.remove(planeName);
		tracks[trackNumber] += TIME_TO_LAND_OR_TAKE_OF;

		return trackNumber;
	}

	// these method returned how much time remains to performing the last
	// registered action in the track in index position
	public int trackActionWillBeDoneIn(int index) {

		return tracks[index];
	}

	// This method throws UnregisteredPlaneExcepton if plane with planeName is
	// not registered
	private void validatePlaneName(String planeName)
			throws UnregisteredPlaneException {
		if (!planesToTracks.containsKey(planeName)) {
			throw new UnregisteredPlaneException(
					"The plane have to be registered to check when the landing/taking off will be performed");
		}
	}

	public void closeTrack(int index, int time) {
		tracks[index] += time;
	}

	public int getNUMBER_OF_TRACKS() {
		return NUMBER_OF_TRACKS;
	}

	public int getCAPACITY() {
		return CAPACITY;
	}

	public int getTIME_TO_LAND_AND_TAKE_OF() {
		return TIME_TO_LAND_OR_TAKE_OF;
	}

	public int getPlaneTrack(String planeName)
			throws UnregisteredPlaneException {

		validatePlaneName(planeName);

		return planesToTracks.get(planeName);
	}

	public void onTimerTick() {

		for (int i = 0; i < tracks.length; ++i) {
			if (tracks[i] > 0)
				--tracks[i];
		}
	}

}
